
package mdr;

import java.lang.reflect.Method;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

class ReadWriteFields {
  
  /**
   * Variable name and frequency
   * */
  final Map<String, Integer> readFields = new LinkedHashMap<String, Integer>();
  final Map<String, Integer> writeFields = new LinkedHashMap<String, Integer>();
  /**
   * The method calls
   * */
  final Set<Method> calls = new LinkedHashSet<Method>();
  final Set<Class<?>> callClass = new LinkedHashSet<Class<?>>();

  final Set<Class<?>> returnTyp = new LinkedHashSet<Class<?>>(); 
  final Set<Class<?>> argusTyp = new LinkedHashSet<Class<?>>();
  final Set<Class<?>> constructors = new LinkedHashSet<Class<?> >();

  ReadWriteFields cloneWithoutCalls() {
    ReadWriteFields retInstance = new ReadWriteFields();
    for(Entry<String, Integer> readField : readFields.entrySet()) {
      retInstance.readFields.put(readField.getKey(), readField.getValue());
    }
    for(Entry<String, Integer> writeField : writeFields.entrySet()) {
      retInstance.writeFields.put(writeField.getKey(), writeField.getValue());
    }
    retInstance.calls.addAll(this.calls);
    retInstance.callClass.addAll(this.callClass);
    retInstance.returnTyp.addAll(this.returnTyp);
    retInstance.argusTyp.addAll(this.argusTyp);

    return retInstance;
  }
  
  void read(String fieldName) {
    this.updateMap(readFields, fieldName, 1);
  }
  
  void read(String fieldName, int num) {
    this.updateMap(readFields, fieldName, num);
  }
  
  void write(String fieldName) {
    this.updateMap(writeFields, fieldName, 1);
  }
  
  void write(String fieldName, int num) {
    this.updateMap(writeFields, fieldName, num);
  }
  
  private void updateMap(Map<String, Integer> map, String fieldName, int num) {
    if(!map.containsKey(fieldName)) {
      map.put(fieldName, 0);
    }
    map.put(fieldName, map.get(fieldName) + num);
  }
  
  void call(Method method) {
    if(method == null) {
      return;
    }
    this.calls.add(method);
  }
  void call(Set<Method> method) {
	    if(method == null) {
	      return;
	    }
	    this.calls.addAll(method);
	  }

  Set<Method> calls() {
    return this.calls;
  }
  void callClass(Class<?> cls) {
	    if(cls == null) {
	      return;
	    }
	    this.callClass.add(cls);
	  }
	  
	  Set<Class<?>> callClass() {
	    return this.callClass;
	  }
 
  void clearCalls() {
    calls.clear();
  }
  void clearWriteFields(){
	  writeFields.clear();
  }
  void argusTyp(Set<Class<?>> clz) {
	    if(clz == null) {
	      return;
	    }
	    this.argusTyp.addAll(clz);
	  }
	  
	  Set<Class<?>> argusTyp() {
	    return this.argusTyp;
	  }
	  
	  void clearArgusTyp() {
		  argusTyp.clear();
	  }
	  void returnTyp(Class<?> clz) {
		    if(clz == null) {
		      return;
		    }
		    this.returnTyp.add(clz);
		  }
		  
		  Set<Class<?>> returnTyp() {
		    return this.returnTyp;
		  }
		  
		  void clearReturnTyp() {
			  returnTyp.clear();
		  }

}
